/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GUI;

import MiddleLayer.Card;
import MiddleLayer.Cards;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;

/**
 *
 * @author Green
 */
public class Gambler implements IMotionFinish {

    //public static
    private String strName;
    private int iID;
    public ArrayList<GUICard> lstAvailableCards;
    public ArrayList<GUICard> lstTakenCards;
    int nAvailCardsOnTheWay = 0;
    int nTakenCardsOnTheWay = 0;
    public ArrayList<GUICard> lstCardsToPass;
    //Vị trí góc trên trái của quân bài đầu tiên.
    //Dùng để sắp xếp bài bắt đầu từ vị trí này
    public Point position;
    //Hướng để xếp bài
    public Point direction;
    //Hướng đến banker
    public Point bankerDirection;
    //Vị trí đặt tên
    public Point namePosition;
    //Khoảng cách chồng lên nhau giữa 2 lá bài liên tiếp
    public Point overlap = new Point(20, 66);
    public Point noname = new Point(GUICard.width / 2, 20);
    Font font = new Font("Arial", Font.BOLD, 16);

    //Tên của người chơi được cấp bởi Server.
    //Chỉ dùng để hiển thị cho người chơi thấy tên của những người khác.
    public String getName() {
        return this.strName;
    }

    public void setName(String name) {
        this.strName = name;
    }

    //ID của người chơi được cấp bởi Server
    //Dùng phân biệt người chơi trong quá trình xử lý,truyền nhận Client-Server
    public int getID() {
        return iID;
    }

    public void setID(int id) {
        this.iID = id;
    }

    public boolean isReadyToPass() {
        return this.lstCardsToPass.size() == 3;
    }

    public Gambler(int id, String name) {
        this.strName = name;
        this.iID = id;
        this.lstAvailableCards = new ArrayList<GUICard>();
        this.lstTakenCards = new ArrayList<GUICard>();
        this.lstCardsToPass = new ArrayList<GUICard>();
    }

    public void receiveCard(GUICard card) {
        this.lstAvailableCards.add(card);
    }

    //Xui bị dính
    public void receiveLostCards(ArrayList<GUICard> list) {
        for (int i = 0; i < list.size(); i++) {
            GUICard card = list.get(i);
            if (card.suit == GUICard.HEARTS || card.isQueenOfSpade()) {
                this.lstTakenCards.add(card);
                continue;
            }
        }

        this.sortTakenCards();
    }

    //Kiểm tra card có hợp lệ ko (chỉ đầm bích và bộ cơ)
    public void receiveLostCard(GUICard card) {
        if (card.suit == GUICard.HEARTS || card.isQueenOfSpade()) {
            this.lstTakenCards.add(card);
            this.sortTakenCards();
        }
    }

    public void receivePassedCards(ArrayList<GUICard> list) {
        this.lstAvailableCards.addAll(list);
        this.sortAvailCards();
        this.lstCardsToPass.clear();
    }

    private void removedPassedCards() {
        this.lstAvailableCards.removeAll(this.lstCardsToPass);
    }

    public void selectCardToPass(Point mousePosition) {
        GUICard card = this.getHitCard(mousePosition);
        if (card == null) {
            return;
        }
        //Nếu card này được chọn và nếu nó đã co trong ds được chọn
        //thì việc click thêm cai nữa vào nó sẽ được hiểu là ko chọn nó nữa
        int index = this.lstCardsToPass.indexOf(card);
        if (index != -1) {
            this.lstCardsToPass.remove(card);
            this.moveDown(card);
        } else {
            if (this.lstCardsToPass.size() < 3) {
                this.lstCardsToPass.add(card);
                this.moveUp(card);
            }
        }
    }

    public void selectCardToPass(ArrayList<GUICard> list) {
        for (int i = this.lstAvailableCards.size() - 1; i >= 0; i--) {
            GUICard card = this.lstAvailableCards.get(i);
            for (int j = 0; j < list.size(); j++) {
                GUICard fake = list.get(j);
                if (card.compareTo(fake) == 0) {
                    int index = this.lstCardsToPass.indexOf(card);
                    if (index != -1) {
                        this.moveDown(card);
                    } else {
                        this.lstCardsToPass.add(card);
                        this.moveUp(card);
                    }

                    break;
                }
            }
        }
    }

    public void selectCardToPass(int rank, int suit) {
        GUICard card = this.findCardInAvailList(rank, suit);
        assert card == null : "selectCardToPass: card == null";

        if(card == null)
             return;
        
        //Nếu card này được chọn và nếu nó đã co trong ds được chọn
        //thì việc click thêm cai nữa vào nó sẽ được hiểu là ko chọn nó nữa
        int index = this.lstCardsToPass.indexOf(card);
        if (index != -1) {
            this.moveDown(card);
        } else {
            this.lstCardsToPass.add(card);
            this.moveUp(card);
        }
    }

    public GUICard findCardInAvailList(int rank, int suit) {
        for (int i = 0; i < this.lstAvailableCards.size(); i++) {
            GUICard card = this.lstAvailableCards.get(i);
            if (card.rank == rank && card.suit == suit) {
                return card;
            }
        }

        return null;
    }

    public ArrayList<GUICard> findCardsInAvailList(int suit) {
        ArrayList<GUICard> result = new ArrayList<GUICard>();
        for (int i = 0; i < this.lstAvailableCards.size(); i++) {
            GUICard card = this.lstAvailableCards.get(i);
            if (card.suit == suit) {
                result.add(card);
            }
        }

        return result;
    }

    public ArrayList<GUICard> findCardsInAvailListExcept(int suit) {
        ArrayList<GUICard> result = new ArrayList<GUICard>();
        for (int i = 0; i < this.lstAvailableCards.size(); i++) {
            GUICard card = this.lstAvailableCards.get(i);
            if (card.suit != suit) {
                result.add(card);
            }
        }

        return result;
    }

    public ArrayList<GUICard> popAllsSelectedCards() {
        this.moveDown3SelectedCards();
        ArrayList<GUICard> list = (ArrayList<GUICard>) this.lstCardsToPass.clone();
        this.removedPassedCards();

        return list;

//        from.moveDown3SelectedCards();
//        to.moveDown3SelectedCards();
//
//        ArrayList<GUICard> list_from = (ArrayList<GUICard>) from.lstCardsToPass.clone();
//        ArrayList<GUICard> list_to = (ArrayList<GUICard>) to.lstCardsToPass.clone();
//        from.removedPassedCards();
//        from.receivePassedCards(list_to);
//        to.removedPassedCards();
//        to.receivePassedCards(list_from);
    }

    public void moveDown3SelectedCards() {
        for (int i = 0; i < this.lstCardsToPass.size(); i++) {
            GUICard card = this.lstCardsToPass.get(i);
            this.moveDown(card);
        }
    }

    private void moveUp(GUICard card) {
        int x = card.position.x + this.noname.x * this.bankerDirection.x;
        int y = card.position.y + this.noname.y * this.bankerDirection.y;

        card.position.x = x;
        card.position.y = y;
    }

    private void moveDown(GUICard card) {
        if (this.bankerDirection.x != 0) {
            card.position.x = this.position.x;
        }
        if (this.bankerDirection.y != 0) {
            card.position.y = this.position.y;
        }
    }

    public void playCard(int rank, int suit, Banker banker) {
        GUICard card = this.findCardInAvailList(rank, suit);
        assert card == null : "Card is not exist in Gambler's list";

        card.setSide(true);
        Hearts.motionManager.addMotion_PlayCard(card, this, banker);
        this.lstAvailableCards.remove(card);
        this.sortAvailCards();
    }

    public GUICard getHitCard(Point mousePosition) {
        for (int i = this.lstAvailableCards.size() - 1; i >= 0; i--) {
            GUICard card = this.lstAvailableCards.get(i);
            if (card.hit(mousePosition)) {
                return card;
            }
        }

        return null;
    }

    public void sortAvailCards() {
        Collections.sort(this.lstAvailableCards);
        this.rearrangePosition(this.lstAvailableCards);
    }

    public void sortTakenCards() {
        Collections.sort(this.lstTakenCards);
        this.rearrangePosition(this.lstTakenCards);
    }

    private void rearrangePosition(ArrayList<GUICard> list) {
        for (int i = 0; i < list.size(); i++) {
            int x = this.position.x + (GUICard.width - this.overlap.x) * i * this.direction.x;
            int y = this.position.y + (GUICard.height - this.overlap.y) * i * this.direction.y;

            GUICard card = list.get(i);
            card.position = new Point(x, y);
        }
    }

    public Point getNextPosition() {
        Point p = new Point();
        int i = this.nAvailCardsOnTheWay;
        this.nAvailCardsOnTheWay++;
        p.x = this.position.x + i * (GUICard.width - this.overlap.x) * this.direction.x;
        p.y = this.position.y + i * (GUICard.height - this.overlap.y) * this.direction.y;
        return p;
    }

    public Point getNextPosition_TakenCard() {
        Point p = new Point();
        int i = this.nTakenCardsOnTheWay;
        this.nTakenCardsOnTheWay++;
        p.x = this.position.x + i * (GUICard.width - this.overlap.x) * this.direction.x;
        p.y = this.position.y + i * (GUICard.height - this.overlap.y) * this.direction.y;
        return p;
    }

    /**
     *
     * @return Trả về giá trị id theo CardID (Lớp bên dưới)
     */
    public Cards getGamblerCards() {
        Cards c = new Cards();
        for (int i = 0; i < this.lstAvailableCards.size(); i++) {
            GUICard guicard = this.lstAvailableCards.get(i);
            c.addCard(Card.convertCardGUI_IDToCard_ID(guicard.toCardID()));
        }

        return c;
    }

    public void showAllsAvailsCard() {
        for (int i = 0; i < this.lstAvailableCards.size(); i++) {
            GUICard card = this.lstAvailableCards.get(i);
            card.setSide(true);
        }
    }

    public void hideAllsAvailsCard() {
        for (int i = 0; i < this.lstAvailableCards.size(); i++) {
            GUICard card = this.lstAvailableCards.get(i);
            card.setSide(false);
        }
    }

    public void drawAllsCards(Graphics g) {
        for (int i = 0; i < this.lstAvailableCards.size(); i++) {
            GUICard card = this.lstAvailableCards.get(i);
            card.draw(g);
        }
    }

    public void drawTakenCard(Graphics g) {
        for (int i = 0; i < this.lstTakenCards.size(); i++) {
            GUICard card = this.lstTakenCards.get(i);
            card.draw(g);
        }
    }

    public void drawName(Graphics g) {
        Color oldColor = g.getColor();
        Font oldFont = g.getFont();

        g.setColor(Color.RED);
        g.setFont(font);

        g.drawString(strName, this.namePosition.x, this.namePosition.y);

        g.setColor(oldColor);
        g.setFont(oldFont);
    }

    public void reset() {
        this.lstAvailableCards.clear();
        this.lstCardsToPass.clear();
        this.lstTakenCards.clear();

        this.nAvailCardsOnTheWay = 0;
        this.nTakenCardsOnTheWay = 0;
    }

    public void end(Motion motion) {
        Motion.MType type = motion.getType();
        GUICard card = motion.getCard();

        if (type == Motion.MType.Lose) {
            this.receiveLostCard(card);
            return;
        }
        if (type == Motion.MType.Deal) {
            this.receiveCard(card);
            if (this.lstAvailableCards.size() == 13) {
                this.nAvailCardsOnTheWay = 0;
                this.sortAvailCards();
                if (this.iID == 0)//player)
                {
                    this.showAllsAvailsCard();
                }
            }
            return;
        }
    }
}
